/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_D3DMAPPINGS_H
#define M_D3DMAPPINGS_H

#include "dxheaders.h"

#include "common.h"
#include "blendmode.h"
#include "presentparams.h"
#include "Matrix4.h"
#include "vertexdeclaration.h"
#include "rendersystem.h"

namespace Engine
{
	/**
	*   Class used for conversions from internal types to Direct3D types.
	*/
	class DXMappings
	{
	public:
		/**
		*   Return a D3D9 equivalent presentation parameters.
		*/
		static void Get(D3DPRESENT_PARAMETERS* d3dprams,const PresentParams& pp);

		/**
		*   Return a D3D9 equivalent for a SceneBlendFactor value.
		*/
		static D3DBLEND Get(SceneBlendFactor sbf);

		/**
		*   Convert our matrix to Direct3D matrix.
		*/
		template<class Real>
		static D3DXMATRIX MakeD3DXMatrix( const Matrix4<Real>& mat );

		/**
		*   Convert Direct3D matrix to our matrix.
		*/
		template<class Real>
		static Matrix4<Real> ConvertD3DXMatrix( const D3DXMATRIX& mat );

		/**
		*   Return a D3D9 equivalent for a CompareFunction value
		*/
		static DWORD Get(CompareFunction cf);

		/**
		*   Return a D3D9 equivalent for a Ogre PolygonMode value
		*/
		static D3DFILLMODE Get(PolygonMode level);

		/**
		*   Get D3D9 vertex data type.
		*/
		static D3DDECLTYPE Get(VertexElementType vType);

		/**
		*   Get D3D9 vertex semantic.
		*/
		static D3DDECLUSAGE Get(VertexElementSemantic sem);

		/**
		*    Get D3D9 index buffer type.
		*/
		static D3DFORMAT Get(IndexType type);

		/**
		*   Get D3D9 shade mode
		*/
		static D3DSHADEMODE Get(ShadeMode val);

		/**
		*   Get D3D9 cull mode
		*/
		static D3DCULL Get(FaceCullMode val);

		/**
		*    Get D3D9 fog mode.
		*/
		static D3DFOGMODE Get(FogMode fm);

		/**
		*   Get D3D9 stencil operation.
		*/
		static DWORD Get(StencilOperation op);

		/**
		*   Get D3D9 texture coordinates  method.
		*/
		static DWORD Get(TexCoordCalcMethod m, const D3DCAPS9& caps);

		/**
		*   Get D3D9 texture addressing mode.
		*/
		static DWORD Get(TextureAddressingMode m, const D3DCAPS9& caps);

		/**
		*    Get D3D9 filter type.
		*/
		static D3DSAMPLERSTATETYPE Get(FilterType ft);

		/**
		*   Get D3D9 filter options.
		*/
		static DWORD Get(FilterOptions fo);

		/**
		*    Get D3D9 blend operation.
		*/
		static DWORD Get(LayerBlendOperationEx lbo, const D3DCAPS9& devCaps);

		/**
		*   Get D3D9 blend source.
		*/
		static DWORD Get(LayerBlendSource lbs);

		/**
		*   Get D3D9 texture coordinate dimension.
		*/
		static DWORD Get(TexCoordDim tcd);

		/**
		*   Get D3D9 primitive type
		*/
		static D3DPRIMITIVETYPE Get(PrimitiveType type);
	};
	/*******************************************************************************/
	template<class Real>
	D3DXMATRIX DXMappings::MakeD3DXMatrix( const Matrix4<Real>& mat )
	{
		// Transpose matrix
		// D3D9 uses row vectors i.e. V*M
		D3DXMATRIX d3dMat;
		d3dMat.m[0][0] = static_cast<float>(mat[0][0]);
		d3dMat.m[0][1] = static_cast<float>(mat[1][0]);
		d3dMat.m[0][2] = static_cast<float>(mat[2][0]);
		d3dMat.m[0][3] = static_cast<float>(mat[3][0]);

		d3dMat.m[1][0] = static_cast<float>(mat[0][1]);
		d3dMat.m[1][1] = static_cast<float>(mat[1][1]);
		d3dMat.m[1][2] = static_cast<float>(mat[2][1]);
		d3dMat.m[1][3] = static_cast<float>(mat[3][1]);

		d3dMat.m[2][0] = static_cast<float>(mat[0][2]);
		d3dMat.m[2][1] = static_cast<float>(mat[1][2]);
		d3dMat.m[2][2] = static_cast<float>(mat[2][2]);
		d3dMat.m[2][3] = static_cast<float>(mat[3][2]);

		d3dMat.m[3][0] = static_cast<float>(mat[0][3]);
		d3dMat.m[3][1] = static_cast<float>(mat[1][3]);
		d3dMat.m[3][2] = static_cast<float>(mat[2][3]);
		d3dMat.m[3][3] = static_cast<float>(mat[3][3]);

		return d3dMat;
	}
	/*******************************************************************************/
	template<class Real>
	Matrix4<Real> DXMappings::ConvertD3DXMatrix( const D3DXMATRIX& mat )
	{
		Matrix4<Real> ourMat;
		ourMat[0][0] = static_cast<Real>(mat.m[0][0]);
		ourMat[1][0] = static_cast<Real>(mat.m[0][1]);
		ourMat[2][0] = static_cast<Real>(mat.m[0][2]);
		ourMat[3][0] = static_cast<Real>(mat.m[0][3]);

		ourMat[0][1] = static_cast<Real>(mat.m[1][0]);
		ourMat[1][1] = static_cast<Real>(mat.m[1][1]);
		ourMat[2][1] = static_cast<Real>(mat.m[1][2]);
		ourMat[3][1] = static_cast<Real>(mat.m[1][3]);

		ourMat[0][2] = static_cast<Real>(mat.m[2][0]);
		ourMat[1][2] = static_cast<Real>(mat.m[2][1]);
		ourMat[2][2] = static_cast<Real>(mat.m[2][2]);
		ourMat[3][2] = static_cast<Real>(mat.m[2][3]);

		ourMat[0][3] = static_cast<Real>(mat.m[3][0]);
		ourMat[1][3] = static_cast<Real>(mat.m[3][1]);
		ourMat[2][3] = static_cast<Real>(mat.m[3][2]);
		ourMat[3][3] = static_cast<Real>(mat.m[3][3]);

		return ourMat;
	}
	/*******************************************************************************/
}

#endif
